<template>
  <el-dialog v-model="visible" :width="props.width" destroy-on-close center align-cente :show-close="false" :close-on-click-modal="false" v-bind="$attrs">
    <template #header>
      <div class="title flex-row-center-between pdb10">
        <div class="bold">{{ props.title }}</div>
        <el-button :loading="loading" type="danger" @click="visible = false"> 关闭 </el-button>
      </div>
    </template>
    <div style="max-height: 500px; min-height: 300px; overflow: auto">
      <el-form ref="formEl" label-width="90" :model="props.formData" :rules="props.rules">
        <slot></slot>
      </el-form>
    </div>
    <template #footer>
      <div class="flex-row-center-right">
        <slot name="btnSlot1"></slot>
        <el-button :loading="loading" @click="visible = false">取消</el-button>
        <slot name="btnSlot2"></slot>
        <el-button v-if="props.showConfirmBtn" :loading="loading" type="primary" @click="handleConfirm"> 确认 </el-button>
        <slot name="btnSlot3"></slot>
      </div>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup>
  import { ref } from 'vue'
  import type { FormInstance } from 'element-plus'
  import request from '@/service'
  import { Ui } from '@/utils'
  import type { ValidateFn } from '../index'

  const props = defineProps({
    formData: {
      type: Object,
      default: () => ({})
    },
    rules: {
      type: Object,
      default: () => ({})
    },
    api: {
      type: String,
      default: ''
    },
    apiMethod: {
      type: String,
      default: 'post'
    },
    title: {
      type: String,
      default: '标题'
    },
    width: {
      type: Number,
      default: 800
    },
    showConfirmBtn: {
      type: Boolean,
      default: true
    }
  })

  interface IEmits {
    (e: 'submit-success'): void
    (e: 'before-submit', data: any, fn: ValidateFn): void
    (e: 'refactor-params', data: any, fn: ValidateFn): void
  }

  const emits = defineEmits<IEmits>()

  const formEl = ref<FormInstance | null>()

  const visible = ref(false)
  const loading = ref(false)

  /**----------------------------methods----------------------------------------------------------------------- */

  const handleConfirm = () => {
    let continueSubmit = true
    let tipMsg = ''
    emits('before-submit', props.formData, (v: boolean, msg: string = '') => {
      continueSubmit = v
      tipMsg = msg
    })

    if (tipMsg) Ui.useMessage('warning', tipMsg)
    if (!continueSubmit) return

    formEl.value?.validate(v => {
      if (!v) return

      let infoContinueSubmit = true
      let infoTipMsg = ''

      emits('refactor-params', props.formData, (v: boolean, msg: string = '') => {
        infoContinueSubmit = v
        infoTipMsg = msg
      })

      if (infoTipMsg) Ui.useMessage('warning', infoTipMsg)
      if (!infoContinueSubmit) return

      if (!props.api) return

      loading.value = true
      request[props.apiMethod as 'post' | 'put'](props.api, props.formData)
        .then(res => {
          if (res.code !== 0) return Ui.useMessage('error', res.msg)

          Ui.useMessage('success', res.msg)

          emits('submit-success')

          handleClose()
        })
        .finally(() => (loading.value = false))
    })
  }

  const handleOpen = () => (visible.value = true)

  const handleClose = () => {
    visible.value = false
  }

  const setLoading = (load: boolean) => (loading.value = load)

  /**----------------------------lifecycle----------------------------------------------------------------------- */

  defineExpose({
    handleOpen,
    handleClose,
    setLoading
  })
</script>

<style scoped lang="less">
  .title {
    border-bottom: 2px solid #ebeef5;
  }
</style>
